package com.netease.nie.facade;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.netease.nie.base.cache.redis.Redis;
import com.netease.nie.base.utils.CopyUtils;
import com.netease.nie.base.utils.CustomDateFormatUtils;
import com.netease.nie.base.utils.DateUtils;
import com.netease.nie.base.utils.JsonUtils;
import com.netease.nie.base.utils.PageUtils;
import com.netease.nie.common.CommonBusinessTools;
import com.netease.nie.constants.CachePrefixConstants;
import com.netease.nie.constants.DisplayTypeConstants;
import com.netease.nie.constants.NextPeriodTypeConstants;
import com.netease.nie.constants.PublishedConstants;
import com.netease.nie.constants.RobGoodsDetailStatusConstants;
import com.netease.nie.dto.GoodsInfoDto;
import com.netease.nie.dto.GoodsInfoImageDto;
import com.netease.nie.dto.RobGoodsConfigDto;
import com.netease.nie.dto.RobGoodsDetailBaseInfoDto;
import com.netease.nie.dto.RobGoodsDetailDto;
import com.netease.nie.dto.RobGoodsDetailSnapshotDto;
import com.netease.nie.dto.RobGoodsInfoDto;
import com.netease.nie.dto.RobGoodsInfoExtendDto;
import com.netease.nie.dto.RobGoodsInfoPeriodDto;
import com.netease.nie.dto.RobGoodsInfoPeriodSnapshotDto;
import com.netease.nie.dto.RobGoodsPeriodComputeResultDto;
import com.netease.nie.dto.RobGoodsPeriodComputeResultSnapshotDto;
import com.netease.nie.dto.RobGoodsPeriodPersonTimeDto;
import com.netease.nie.dto.RobGoodsPeriodPersonTimeRecordDto;
import com.netease.nie.dto.RobGoodsPeriodUserPersonTimeDto;
import com.netease.nie.dto.RobGoodsSnapshotDto;
import com.netease.nie.dto.RobbedGoodsDto;
import com.netease.nie.service.GoodsInfoImageService;
import com.netease.nie.service.GoodsInfoService;
import com.netease.nie.service.RobGoodsInfoExtendService;
import com.netease.nie.service.RobGoodsInfoPeriodService;
import com.netease.nie.service.RobGoodsInfoService;
import com.netease.nie.service.RobGoodsPeriodComputeResultService;
import com.netease.nie.service.RobGoodsPeriodPersonTimeService;

@Service
public class RobGoodsFacadeImpl extends CommonBusinessTools implements RobGoodsFacade {

	private static final int PAGE_SIZE = 20;
	
	private static final String ROB_GOODS_TOP_LIST = "Rob_Goods_Top_List";
	
	private static final String ROB_GOODS_MORE_LIST = "Rob_Goods_More_List";
	
	private static final String ROB_GOODS_ID_DISPLAYPERIOD_PREFIX = CachePrefixConstants.RobGoodsPrefix.ROB_GOODS_ID_DISPLAYPERIOD_PREFIX;
	
	private static final String ROB_GOODS_PERIOD_REMAIN_PT_PREFIX = CachePrefixConstants.RobGoodsPrefix.ROB_GOODS_PERIOD_REMAIN_PT_PREFIX;
	
	private static final String ROB_GOODS_DISPLAYPERIOD_PT_LIST_PREFIX = CachePrefixConstants.RobGoodsPrefix.ROB_GOODS_DISPLAYPERIOD_PT_LIST_PREFIX;
	
	private static final String ROB_GOODS_PREVIOUS_PUBLISHED_LIST_PREFIX = CachePrefixConstants.RobGoodsPrefix.ROB_GOODS_PREVIOUS_PUBLISHED_LIST_PREFIX;
	
	private static final String ROB_GOODS_PERIOD_COMPUTE_RESULT_SNAPSHOT_PREFIX = CachePrefixConstants.RobGoodsPrefix.ROB_GOODS_PERIOD_COMPUTE_RESULT_SNAPSHOT_PREFIX;
	
	private static final String ROB_GOODS_DETAIL_BASE_INFO_PREFIX = CachePrefixConstants.RobGoodsPrefix.ROB_GOODS_DETAIL_BASE_INFO_PREFIX;
	
	private static final String ROB_GOODS_PERIOD_PREFIX = CachePrefixConstants.RobGoodsPrefix.ROB_GOODS_PERIOD_PREFIX;
	
	private static final String ROB_GOODS_PERIOD_USER_PT_PREFIX = CachePrefixConstants.RobGoodsPrefix.ROB_GOODS_PERIOD_USER_PT_PREFIX;
	
	private static final String ROB_GOODS_NEXT_PREIOD_CONFIG_PREFIX = CachePrefixConstants.RobGoodsPrefix.ROB_GOODS_NEXT_PREIOD_CONFIG_PREFIX;
	
	@Autowired
	private RobGoodsInfoService robGoodsInfoService;
	
	@Autowired
	private RobGoodsInfoExtendService robGoodsInfoExtendService;
	
	@Autowired
	private GoodsInfoService goodsInfoService;
	
	@Autowired
	private GoodsInfoImageService goodsInfoImageService;
	
	@Autowired
	private RobGoodsInfoPeriodService robGoodsInfoPeriodService;
	
	@Autowired
	private RobGoodsPeriodPersonTimeService robGoodsPeriodPersonTimeService;
	
	@Autowired
	private RobGoodsPeriodComputeResultService robGoodsPeriodComputeResultService;
	
	@Autowired
	private Redis redis;
	
	public List<RobGoodsSnapshotDto> queryTopRobGoodsSnapshotDtos() {
		List<RobGoodsSnapshotDto> robGoodsSnapshotDtos = null;
		List<RobGoodsInfoDto> robGoodsInfoDtoList = null;
		boolean exists = redis.exists(ROB_GOODS_TOP_LIST);
		if (!exists) {
			robGoodsInfoDtoList = robGoodsInfoService.queryTopRobGoodsInfoDtos();
			if (robGoodsInfoDtoList != null && !robGoodsInfoDtoList.isEmpty())
				redis.rpush(ROB_GOODS_TOP_LIST, robGoodsInfoDtoList);
		} else
			robGoodsInfoDtoList = redis.lrange(ROB_GOODS_TOP_LIST, 0, 3, RobGoodsInfoDto.class);
		
		if (robGoodsInfoDtoList != null && !robGoodsInfoDtoList.isEmpty()) {
			robGoodsSnapshotDtos = new ArrayList<>();
			Map<Integer, Integer> robGoodsIdDisplayPeriodMapper = generateRobGoodsDisplayPeriodMapper(robGoodsInfoDtoList);
			Map<Integer, Integer> robGoodsDisplayPeriodRemainPtMapper = generateRobGoodsDisplayPeriodRemainPt(robGoodsIdDisplayPeriodMapper);
			generateRobGoodsSnapshotDto(robGoodsSnapshotDtos, robGoodsInfoDtoList, robGoodsIdDisplayPeriodMapper, robGoodsDisplayPeriodRemainPtMapper);
			replaceRobGoodsSnapshotDtoThumbnailUrl(robGoodsSnapshotDtos, DisplayTypeConstants.WAP.getCode());
			return robGoodsSnapshotDtos;
		}
		return Collections.emptyList();
	}

	public List<RobGoodsSnapshotDto> queryMoreRobGoodsSnapshotDtos(Integer page) {
		int pageStartIndex = PageUtils.getPageStartIndex(page);
		int pageEndIndex = PageUtils.getPageEndIndex(page);
		List<RobGoodsInfoDto> robGoodsInfoDtoList = null;
		List<RobGoodsSnapshotDto> robGoodsSnapshotDtos = null;
		boolean exists = redis.exists(ROB_GOODS_MORE_LIST);
		if (!exists) {
			robGoodsInfoDtoList = robGoodsInfoService.queryMoreRobGoodsInfoDtos();
			if (robGoodsInfoDtoList != null && !robGoodsInfoDtoList.isEmpty())
				redis.rpush(ROB_GOODS_TOP_LIST, robGoodsInfoDtoList);
			robGoodsInfoDtoList = PageUtils.getPageListByIndex(robGoodsInfoDtoList, pageStartIndex, pageEndIndex);
		} else
			robGoodsInfoDtoList = redis.lrange(ROB_GOODS_MORE_LIST, pageStartIndex, --pageEndIndex, RobGoodsInfoDto.class);
		
		if (robGoodsInfoDtoList != null && !robGoodsInfoDtoList.isEmpty()) {
			robGoodsSnapshotDtos = new ArrayList<>();
			Map<Integer, Integer> robGoodsIdDisplayPeriodMapper = generateRobGoodsDisplayPeriodMapper(robGoodsInfoDtoList);
			Map<Integer, Integer> robGoodsDisplayPeriodRemainPtMapper = generateRobGoodsDisplayPeriodRemainPt(robGoodsIdDisplayPeriodMapper);
			generateRobGoodsSnapshotDto(robGoodsSnapshotDtos, robGoodsInfoDtoList, robGoodsIdDisplayPeriodMapper, robGoodsDisplayPeriodRemainPtMapper);
			replaceRobGoodsSnapshotDtoThumbnailUrl(robGoodsSnapshotDtos, DisplayTypeConstants.WAP.getCode());
			return robGoodsSnapshotDtos;
		}
		
		return Collections.emptyList();
	}
	
	private List<Integer> distillRobGoodsIdList(List<RobGoodsInfoDto> robGoodsInfoDtoList) {
		if (robGoodsInfoDtoList != null && !robGoodsInfoDtoList.isEmpty()) {
			List<Integer> robGoodsIdList = new ArrayList<Integer>();
			RobGoodsInfoDto robGoodsInfoDto = null;
			int robGoodsInfoDtoListSize = robGoodsInfoDtoList.size();
			for (int i = 0; i < robGoodsInfoDtoListSize; i++) {
				robGoodsInfoDto = robGoodsInfoDtoList.get(i);
				robGoodsIdList.add(robGoodsInfoDto.getId());
			}
			return robGoodsIdList;
		}
		return Collections.emptyList();
	}
	
	private Map<Integer, Integer> generateRobGoodsDisplayPeriodMapper(List<RobGoodsInfoDto> robGoodsInfoDtoList) {
		Map<Integer, Integer> robGoodsIdDisplayPeriodMapper = new HashMap<Integer, Integer>();
		List<Integer> robGoodsIdList = distillRobGoodsIdList(robGoodsInfoDtoList);
		int robGoodsIdListSize = robGoodsIdList.size();
		String[] robGoodsIdDisplayPeriodKeys = {};
		String robGoodsIdDisplayPeriodKey = null;
		for (int i = 0; i < robGoodsIdListSize; i++) {
			int robGoodsId = robGoodsIdList.get(i);
			robGoodsIdDisplayPeriodKey = ROB_GOODS_ID_DISPLAYPERIOD_PREFIX + robGoodsId;
			robGoodsIdDisplayPeriodKeys = (String[]) ArrayUtils.add(robGoodsIdDisplayPeriodKeys, robGoodsIdDisplayPeriodKey);
		}
		
		if (robGoodsIdDisplayPeriodKeys.length > 0) {
			List<String> strList = redis.mget(robGoodsIdDisplayPeriodKeys);
			if (strList != null && !strList.isEmpty()) {
				int strListSize = strList.size();
				for (int i = 0; i < strListSize; i++) {
					int robGoodsId = Integer.valueOf(StringUtils.removeStart(robGoodsIdDisplayPeriodKeys[i], CachePrefixConstants.RobGoodsPrefix.ROB_GOODS_ID_DISPLAYPERIOD_PREFIX));
					robGoodsIdDisplayPeriodMapper.put(robGoodsId, Integer.valueOf(strList.get(i)));
				}
			} else {
				List<RobGoodsInfoPeriodDto> robGoodsInfoPeriodDtoList = robGoodsInfoPeriodService.queryMaxPeriodRobGoodsInfoPeriodDtosByRobGoodsIds(robGoodsIdList);
				if (robGoodsInfoPeriodDtoList != null && !robGoodsInfoPeriodDtoList.isEmpty()) {
					int robGoodsInfoPeriodDtoListSize = robGoodsInfoPeriodDtoList.size();
					RobGoodsInfoPeriodDto robGoodsInfoPeriodDto = null;
					String[] keysvalues = {};
					String key = null;
					String value = null;
					List<String> keyValueList = new ArrayList<>();
					for (int i = 0; i < robGoodsInfoPeriodDtoListSize; i++) {
						robGoodsInfoPeriodDto = robGoodsInfoPeriodDtoList.get(i);
						key = ROB_GOODS_ID_DISPLAYPERIOD_PREFIX + robGoodsInfoPeriodDto.getRobGoodsId();
						value = JsonUtils.obj2String(robGoodsInfoPeriodDto.getDisplayPeriod());
						keyValueList.add(key);
						keyValueList.add(value);
						robGoodsIdDisplayPeriodMapper.put(robGoodsInfoPeriodDto.getRobGoodsId(), robGoodsInfoPeriodDto.getDisplayPeriod());
					}
					keysvalues = keyValueList.toArray(keysvalues);
					redis.mset(keysvalues);
				}
			}
		}
		return robGoodsIdDisplayPeriodMapper;
	}
	
	private Map<Integer, Integer> generateRobGoodsDisplayPeriodRemainPt(Map<Integer, Integer> robGoodsIdDisplayPeriodMapper) {
		Map<Integer, Integer> robGoodsDisplayPeriodRemainPtMapper = new HashMap<>();
		if (robGoodsIdDisplayPeriodMapper != null && !robGoodsIdDisplayPeriodMapper.isEmpty()) {
			List<Integer> displayPeriodList = new ArrayList<>();
			Integer[] tempDisplayPeriodArr = {};
			Collections.addAll(displayPeriodList, robGoodsIdDisplayPeriodMapper.values().toArray(tempDisplayPeriodArr));
			int displayPeriodListSize = displayPeriodList.size();
			String[] robGoodsDisplayPeriodRemainPtKeys = {};
			String robGoodsDisplayPeriodRemainPtKey = null;
			for (int i = 0; i < displayPeriodListSize; i++) {
				int displayPeriod = displayPeriodList.get(i);
				robGoodsDisplayPeriodRemainPtKey = ROB_GOODS_PERIOD_REMAIN_PT_PREFIX + displayPeriod;
				robGoodsDisplayPeriodRemainPtKeys = (String[]) ArrayUtils.add(robGoodsDisplayPeriodRemainPtKeys, robGoodsDisplayPeriodRemainPtKey);
			}
			if (robGoodsDisplayPeriodRemainPtKeys.length > 0) {
				List<String> strList = redis.mget(robGoodsDisplayPeriodRemainPtKeys);
				if (strList != null && !strList.isEmpty()) {
					int strListSize = strList.size();
					for (int i = 0; i < strListSize; i++) {
						int displayPeriod = Integer.valueOf(StringUtils.removeStart(robGoodsDisplayPeriodRemainPtKeys[i], CachePrefixConstants.RobGoodsPrefix.ROB_GOODS_PERIOD_REMAIN_PT_PREFIX));
						robGoodsDisplayPeriodRemainPtMapper.put(displayPeriod, Integer.valueOf(strList.get(i)));
					}
				}
			}
		}
		return robGoodsDisplayPeriodRemainPtMapper;
	}
	
	private void generateRobGoodsSnapshotDto(List<RobGoodsSnapshotDto> robGoodsSnapshotDtoList, List<RobGoodsInfoDto> robGoodsInfoDtoList, 
			Map<Integer, Integer> robGoodsIdDisplayPeriodMapper, Map<Integer, Integer> robGoodsDisplayPeriodRemainPtMapper) {
		RobGoodsInfoDto robGoodsInfoDto = null;
		RobGoodsSnapshotDto robGoodsSnapshotDto = null;
		int robGoodsInfoDtoListSize = robGoodsInfoDtoList.size();
		for (int i = 0; i < robGoodsInfoDtoListSize; i++) {
			robGoodsInfoDto = robGoodsInfoDtoList.get(i);
			robGoodsSnapshotDto = new RobGoodsSnapshotDto();
			CopyUtils.copy(robGoodsSnapshotDto, robGoodsInfoDto);
			int robGoodsId = robGoodsInfoDto.getId();
			if (robGoodsIdDisplayPeriodMapper.containsKey(robGoodsId)) {
				Integer displayPeriod = robGoodsIdDisplayPeriodMapper.get(robGoodsId);
				if (displayPeriod != null)
					robGoodsSnapshotDto.setDisplayPeriod(displayPeriod);
				if (robGoodsDisplayPeriodRemainPtMapper.containsKey(displayPeriod)) {
					Integer remainPt = robGoodsDisplayPeriodRemainPtMapper.get(displayPeriod);
					Integer currentPt = robGoodsInfoDto.getTotalPt() - remainPt;
					robGoodsSnapshotDto.setRemainPt(remainPt);
					robGoodsSnapshotDto.setCurrentPt(currentPt);
				}
			}
			robGoodsSnapshotDtoList.add(robGoodsSnapshotDto);
		}
	}

	public RobGoodsPeriodPersonTimeRecordDto queryRobGoodsPeriodPersonTimeRecordDtoByDisplayPeriod(int displayPeriod, int page) {
		RobGoodsPeriodPersonTimeRecordDto robGoodsPeriodPersonTimeRecordDto = new RobGoodsPeriodPersonTimeRecordDto();
		List<RobGoodsPeriodPersonTimeDto> robGoodsPeriodPersonTimeDtoList = null;
		int pageStartIndex = PageUtils.getPageStartIndex(page, 30);
		int pageEndIndex = PageUtils.getPageEndIndex(page, 30);
		String key = ROB_GOODS_DISPLAYPERIOD_PT_LIST_PREFIX + displayPeriod;
		boolean exists = redis.exists(key);
		if (!exists) {
			robGoodsPeriodPersonTimeDtoList = robGoodsPeriodPersonTimeService.queryRobGoodsPeriodPersonTimeDtosByDisplayPeriod(displayPeriod);
			if (robGoodsPeriodPersonTimeDtoList != null && !robGoodsPeriodPersonTimeDtoList.isEmpty())
				redis.rpush(key, robGoodsPeriodPersonTimeDtoList);
			robGoodsPeriodPersonTimeDtoList = PageUtils.getPageListByIndex(robGoodsPeriodPersonTimeDtoList, pageStartIndex, pageEndIndex);
		} else
			robGoodsPeriodPersonTimeDtoList = redis.lrange(key, pageStartIndex, --pageEndIndex, RobGoodsPeriodPersonTimeDto.class);
		
		if (robGoodsPeriodPersonTimeDtoList != null && !robGoodsPeriodPersonTimeDtoList.isEmpty()) {
			RobGoodsPeriodPersonTimeDto robGoodsPeriodPersonTimeDto = robGoodsPeriodPersonTimeDtoList.get(0);
			Long periodStartTime = robGoodsPeriodPersonTimeDto.getPeriodStartTime();
			String periodStartTimeStr = CustomDateFormatUtils.getyyyyMMddHHmmssSSS2Str(periodStartTime);
			robGoodsPeriodPersonTimeRecordDto.setPeriodStartTimeStr(periodStartTimeStr);
			transRobGoodsPeriodPersonTimeDtoIp(robGoodsPeriodPersonTimeDtoList);
		}
		robGoodsPeriodPersonTimeRecordDto.setRobGoodsPeriodPersonTimeDtos(robGoodsPeriodPersonTimeDtoList);
		return robGoodsPeriodPersonTimeRecordDto;
	}
	
	private void transRobGoodsPeriodPersonTimeDtoIp(List<RobGoodsPeriodPersonTimeDto> robGoodsPeriodPersonTimeDtoList) {
		if (robGoodsPeriodPersonTimeDtoList != null && !robGoodsPeriodPersonTimeDtoList.isEmpty()) {
			int robGoodsPeriodPersonTimeDtoListSize = robGoodsPeriodPersonTimeDtoList.size();
			RobGoodsPeriodPersonTimeDto robGoodsPeriodPersonTimeDto = null;
			String robUserIp;
			for (int i = 0; i < robGoodsPeriodPersonTimeDtoListSize; i++) {
				robGoodsPeriodPersonTimeDto = robGoodsPeriodPersonTimeDtoList.get(i);
				robUserIp = robGoodsPeriodPersonTimeDto.getRobUserIp();
				if (robUserIp.indexOf("::ffff:") > -1)
					robGoodsPeriodPersonTimeDto.setRobUserIp(robUserIp.replaceAll("::ffff:", ""));
			}
		}
	}

	public List<RobGoodsInfoPeriodSnapshotDto> queryRobGoodsInfoPeriodSnapshotDtosByRobGoodsId(
			int robGoodsId) {
		String key = ROB_GOODS_PREVIOUS_PUBLISHED_LIST_PREFIX + robGoodsId;
		List<RobGoodsInfoPeriodDto> robGoodsInfoPeriodDtoList = null;
		boolean exists = redis.exists(key);
		if (!exists) {
			robGoodsInfoPeriodDtoList = robGoodsInfoPeriodService.queryRobGoodsInfoPublishedPeriodDtosByRobGoodsId(robGoodsId);
			if (robGoodsInfoPeriodDtoList != null && !robGoodsInfoPeriodDtoList.isEmpty())
				redis.rpush(key, robGoodsInfoPeriodDtoList);
		} else
			robGoodsInfoPeriodDtoList = redis.lrange(key, 0, -1, RobGoodsInfoPeriodDto.class);
		
		if (robGoodsInfoPeriodDtoList != null && !robGoodsInfoPeriodDtoList.isEmpty()) {
			int robGoodsInfoPeriodDtoListSize = robGoodsInfoPeriodDtoList.size();
			List<RobGoodsInfoPeriodSnapshotDto> robGoodsInfoPeriodSnapshotDtoList = new ArrayList<>();
			RobGoodsInfoPeriodDto robGoodsInfoPeriodDto = null;
			RobGoodsInfoPeriodSnapshotDto robGoodsInfoPeriodSnapshotDto = null;
			for (int i = 0; i < robGoodsInfoPeriodDtoListSize; i++) {
				robGoodsInfoPeriodSnapshotDto = new RobGoodsInfoPeriodSnapshotDto();
				robGoodsInfoPeriodDto = robGoodsInfoPeriodDtoList.get(i);
				CopyUtils.copy(robGoodsInfoPeriodSnapshotDto, robGoodsInfoPeriodDto);
				if (robGoodsInfoPeriodDto.getPublished() == PublishedConstants.PUBLISHED.getCode())
					robGoodsInfoPeriodSnapshotDto.setPublishedTimeStr(CustomDateFormatUtils.getyyyyMMddHHmmssSSS2Str(robGoodsInfoPeriodDto.getPublishedTime()));
				else if (robGoodsInfoPeriodDto.getPublished() == PublishedConstants.PREPARED_PUBLISHED.getCode()) {
					if (robGoodsInfoPeriodDto.getPublishedTime() != null) {
						long currentTimeInMills = DateUtils.currentTimeInMills();
						if (currentTimeInMills < robGoodsInfoPeriodDto.getPublishedTime())
							robGoodsInfoPeriodSnapshotDto.setPublishedTimeStr(String.valueOf(robGoodsInfoPeriodDto.getPublishedTime() - currentTimeInMills));
						else 
							robGoodsInfoPeriodSnapshotDto.setPublishedTimeStr("0");
					}
				}
				robGoodsInfoPeriodSnapshotDtoList.add(robGoodsInfoPeriodSnapshotDto);
			}
			return robGoodsInfoPeriodSnapshotDtoList;
		}
		return Collections.emptyList();
	}

	public RobGoodsPeriodComputeResultSnapshotDto queryRobGoodsPeriodComputeResultSnapshotDtoByDisplayPeriod(
			int displayPeriod) {
		RobGoodsPeriodComputeResultSnapshotDto robGoodsPeriodComputeResultSnapshotDto = new RobGoodsPeriodComputeResultSnapshotDto();
		String key = ROB_GOODS_PERIOD_COMPUTE_RESULT_SNAPSHOT_PREFIX + displayPeriod;
		boolean exists = redis.exists(key);
		if (!exists) {
			RobGoodsInfoPeriodDto robGoodsInfoPeriodDto = robGoodsInfoPeriodService.queryRobGoodsInfoPeriodDtoByDisplayPeriod(displayPeriod);
			if (robGoodsInfoPeriodDto != null) {
				CopyUtils.copy(robGoodsPeriodComputeResultSnapshotDto, robGoodsInfoPeriodDto);
				List<RobGoodsPeriodComputeResultDto> robGoodsPeriodComputeResultDtoList = robGoodsPeriodComputeResultService.queryRobGoodsPeriodComputeResultDtosByPeriodId(robGoodsInfoPeriodDto.getId());
				if (robGoodsPeriodComputeResultDtoList != null && !robGoodsPeriodComputeResultDtoList.isEmpty())
					robGoodsPeriodComputeResultSnapshotDto.setRobGoodsPeriodComputeResultDtoList(robGoodsPeriodComputeResultDtoList);
				redis.set(key, robGoodsPeriodComputeResultSnapshotDto);
			}
		} else
			robGoodsPeriodComputeResultSnapshotDto = redis.get(key, RobGoodsPeriodComputeResultSnapshotDto.class);
		return robGoodsPeriodComputeResultSnapshotDto;
	}

	public RobGoodsDetailDto queryRobGoodsDetailDtoByCondition(Long userId, int goodsId,
			int robGoodsId, int displayPeriod) {
		boolean userPtStatus = false, periodPublishedStatus = false;
		RobGoodsDetailDto robGoodsDetailDto = new RobGoodsDetailDto();
		RobGoodsDetailBaseInfoDto robGoodsDetailBaseInfoDto = null;
		RobGoodsDetailSnapshotDto robGoodsDetailSnapshotDto = new RobGoodsDetailSnapshotDto();
		String robGoodsDetailBaseInfoDtoKey = ROB_GOODS_DETAIL_BASE_INFO_PREFIX + robGoodsId;
		boolean robGoodsDetailBaseInfoDtoKeyExists = redis.exists(robGoodsDetailBaseInfoDtoKey);
		if (!robGoodsDetailBaseInfoDtoKeyExists) {
			robGoodsDetailBaseInfoDto = new RobGoodsDetailBaseInfoDto();
			//夺宝商品信息
			RobGoodsInfoDto robGoodsInfoDto = robGoodsInfoService.queryRobGoodsInfoDtoByRobGoodsId(robGoodsId);
			if (robGoodsInfoDto != null) {
				robGoodsDetailBaseInfoDto.setGoodsId(robGoodsInfoDto.getGoodsId());
				robGoodsDetailBaseInfoDto.setRobGoodsId(robGoodsInfoDto.getId());
				robGoodsDetailBaseInfoDto.setRobGoodsTitle(robGoodsInfoDto.getTitle());
				robGoodsDetailBaseInfoDto.setRobGoodsSubTitle(robGoodsInfoDto.getSubTitle());
				robGoodsDetailBaseInfoDto.setPrice(robGoodsInfoDto.getPrice());
				robGoodsDetailBaseInfoDto.setTotalPt(robGoodsInfoDto.getTotalPt());
			}
			//商品图片
			List<GoodsInfoImageDto> goodsInfoImageDtoList = goodsInfoImageService.queryGoodsInfoImageDtosByGoodsId(goodsId);
			if (goodsInfoImageDtoList != null && !goodsInfoImageDtoList.isEmpty()) {
				robGoodsDetailBaseInfoDto.setGoodsInfoImageDtos(goodsInfoImageDtoList);
			}
			//基础说明
			GoodsInfoDto goodsInfoDto = goodsInfoService.queryGoodsInfoById(goodsId);
			robGoodsDetailBaseInfoDto.setIntroduction(goodsInfoDto.getIntroduction());
			
			//特殊说明
			RobGoodsInfoExtendDto robGoodsInfoExtendDto = robGoodsInfoExtendService.queryRobGoodsInfoExtendDtoByRobGoodsId(robGoodsId);
			if (robGoodsInfoExtendDto != null)
				robGoodsDetailBaseInfoDto.setSpecialIntroduction(robGoodsInfoExtendDto.getSpecialIntroduction());
			
			redis.set(robGoodsDetailBaseInfoDtoKey, robGoodsDetailBaseInfoDto);
		} else
			robGoodsDetailBaseInfoDto = redis.get(robGoodsDetailBaseInfoDtoKey, RobGoodsDetailBaseInfoDto.class);
		
		List<GoodsInfoImageDto> goodsInfoImageDtoList = robGoodsDetailBaseInfoDto.getGoodsInfoImageDtos();
		replaceGoodsInfoImageDto(goodsInfoImageDtoList, DisplayTypeConstants.WAP.getCode());
		CopyUtils.copy(robGoodsDetailSnapshotDto, robGoodsDetailBaseInfoDto);
		
		//个人参与情况
		if (userId != null) {
			List<RobGoodsPeriodUserPersonTimeDto> robGoodsPeriodUserPersonTimeDtoList = null;
			String robGoodsPeriodUserPtKey = ROB_GOODS_PERIOD_USER_PT_PREFIX + userId + "_" + displayPeriod;
			boolean robGoodsPeriodUserPtKeyExists = redis.exists(robGoodsPeriodUserPtKey);
			if (!robGoodsPeriodUserPtKeyExists) {
				robGoodsPeriodUserPersonTimeDtoList = robGoodsPeriodPersonTimeService.queryRobGoodsPeriodUserPersonTimeDtosByDisplayPeriodAndUserId(displayPeriod, userId);
				if (robGoodsPeriodUserPersonTimeDtoList != null && !robGoodsPeriodUserPersonTimeDtoList.isEmpty())
					redis.rpush(robGoodsPeriodUserPtKey, robGoodsPeriodUserPersonTimeDtoList);
			} else
				robGoodsPeriodUserPersonTimeDtoList = redis.lrange(robGoodsPeriodUserPtKey, 0, -1, RobGoodsPeriodUserPersonTimeDto.class);
			
			if (robGoodsPeriodUserPersonTimeDtoList != null && !robGoodsPeriodUserPersonTimeDtoList.isEmpty()) {
				int robGoodsPeriodUserPersonTimeDtoListSize = robGoodsPeriodUserPersonTimeDtoList.size();
				RobGoodsPeriodUserPersonTimeDto robGoodsPeriodUserPersonTimeDto = null;
				int userPt = 0;
				StringBuilder userNumber = new StringBuilder();
				for (int i = 0; i < robGoodsPeriodUserPersonTimeDtoListSize; i++) {
					robGoodsPeriodUserPersonTimeDto = robGoodsPeriodUserPersonTimeDtoList.get(i);
					userPt += robGoodsPeriodUserPersonTimeDto.getRobUserPt();
					userNumber.append(robGoodsPeriodUserPersonTimeDto.getRobUserNumber()).append(",");
				}
				
				int userNumberLen = userNumber.length();
				if (userNumberLen > 0)
					userNumber.deleteCharAt(--userNumberLen);
				
				robGoodsDetailSnapshotDto.setUserNumber(userNumber.toString());
				robGoodsDetailSnapshotDto.setUserPt(userPt);
				userPtStatus = true;
			}
		}
		
		//期号进行状态
		String robGoodsPeriodKey = ROB_GOODS_PERIOD_PREFIX + displayPeriod;
		boolean robGoodsPeriodKeyKeyExists = redis.exists(robGoodsPeriodKey);
		RobGoodsInfoPeriodDto robGoodsInfoPeriodDto = null;
		if (!robGoodsPeriodKeyKeyExists) {
			robGoodsInfoPeriodDto = robGoodsInfoPeriodService.queryRobGoodsInfoPeriodDtoByDisplayPeriod(displayPeriod);
			if (robGoodsInfoPeriodDto != null)
				redis.set(robGoodsPeriodKey, robGoodsInfoPeriodDto);
		} else 
			robGoodsInfoPeriodDto = redis.get(robGoodsPeriodKey, RobGoodsInfoPeriodDto.class);
		
		if (robGoodsInfoPeriodDto != null) {
			Integer published = robGoodsInfoPeriodDto.getPublished();
			robGoodsDetailSnapshotDto.setRemainPt(robGoodsInfoPeriodDto.getRemainPt());
			if (published == PublishedConstants.PUBLISHED.getCode()) {
				robGoodsDetailSnapshotDto.setLuckyNumber(robGoodsInfoPeriodDto.getLuckyNumber());
				robGoodsDetailSnapshotDto.setPublishedTimeStr(CustomDateFormatUtils.getyyyyMMddHHmmssSSS2Str(robGoodsInfoPeriodDto.getPublishedTime()));
				robGoodsDetailSnapshotDto.setRobUserId(robGoodsInfoPeriodDto.getRobUserId());
				robGoodsDetailSnapshotDto.setRobUserNickname(robGoodsInfoPeriodDto.getRobUserNickname());
				robGoodsDetailSnapshotDto.setRobUserPt(robGoodsInfoPeriodDto.getRobUserPt());
				periodPublishedStatus = true;
			}
		}
		
		//剩余人次
		String robGoodsDisplayPeriodRemainPtKey = ROB_GOODS_PERIOD_REMAIN_PT_PREFIX + displayPeriod;
		String remainPtTemp = redis.get(robGoodsDisplayPeriodRemainPtKey);
		if (StringUtils.isNotBlank(remainPtTemp))
			robGoodsDetailSnapshotDto.setRemainPt(Integer.valueOf(remainPtTemp));
		
		
		if (!userPtStatus && !periodPublishedStatus)
			robGoodsDetailDto.setStatus(RobGoodsDetailStatusConstants.NOT_USER_PT_AND_NOT_PUBLISHED.getCode());
		else if (userPtStatus && !periodPublishedStatus)
			robGoodsDetailDto.setStatus(RobGoodsDetailStatusConstants.USER_PT_AND_NOT_PUBLISHED.getCode());
		else if (!userPtStatus && periodPublishedStatus) {
			robGoodsDetailDto.setStatus(RobGoodsDetailStatusConstants.NOT_USER_PT_AND_PUBLISHED.getCode());
			String key = ROB_GOODS_ID_DISPLAYPERIOD_PREFIX + robGoodsDetailSnapshotDto.getRobGoodsId();
			Integer nextDisplayPeriod = redis.get(key, Integer.class);
			if (nextDisplayPeriod != displayPeriod)
				robGoodsDetailSnapshotDto.setNextDisplayPeriod(nextDisplayPeriod);
			else {
				long nextPeriodDiffTime = generateNextPeriodDiffTime(robGoodsId);
				robGoodsDetailSnapshotDto.setNextPeriodDiffTime(nextPeriodDiffTime);
			}
		}
		else if (userPtStatus && periodPublishedStatus) {
			robGoodsDetailDto.setStatus(RobGoodsDetailStatusConstants.USER_PT_AND_PUBLISHED.getCode());
			String key = ROB_GOODS_ID_DISPLAYPERIOD_PREFIX + robGoodsDetailSnapshotDto.getRobGoodsId();
			Integer nextDisplayPeriod = redis.get(key, Integer.class);
			if (nextDisplayPeriod != displayPeriod)
				robGoodsDetailSnapshotDto.setNextDisplayPeriod(nextDisplayPeriod);
			else {
				long nextPeriodDiffTime = generateNextPeriodDiffTime(robGoodsId);
				robGoodsDetailSnapshotDto.setNextPeriodDiffTime(nextPeriodDiffTime);
			}
		}
		robGoodsDetailDto.setRobGoodsDetailSnapshotDto(robGoodsDetailSnapshotDto);
		return robGoodsDetailDto;
	}
	
	private long generateNextPeriodDiffTime(int robGoodsId) {
		RobGoodsConfigDto robGoodsConfigDto = generateRobGoodsConfigDtoByRobGoodsId(robGoodsId);
		if (robGoodsConfigDto != null) {
			Integer nextPeriodType = robGoodsConfigDto.getNextPeriodType();
			if (nextPeriodType == NextPeriodTypeConstants.PREPARE_NEXT_PERIOD.getCode()) {
				String nextPeriodDate = robGoodsConfigDto.getNextPeriodDate();
				Set<Integer> nextPeriodDateSet = generateNextPeriodDateSet(nextPeriodDate);
				long currTimeInMills = DateUtils.currentTimeInMills();
				long nextPeriodTimeInMills = generateNextPeriodTimeInMills(currTimeInMills, nextPeriodDateSet);
				long nextPeriodDiffTime = nextPeriodTimeInMills - currTimeInMills;
				return nextPeriodDiffTime / 1000;
			}
		}
		return 0;
	}
	
	private RobGoodsConfigDto generateRobGoodsConfigDtoByRobGoodsId(int robGoodsId) {
		String robGoodsNextPeriodConfigKey = ROB_GOODS_NEXT_PREIOD_CONFIG_PREFIX + robGoodsId;
		boolean robGoodsNextPeriodConfigKeyExists = redis.exists(robGoodsNextPeriodConfigKey);
		RobGoodsConfigDto robGoodsConfigDto = null;
		if (!robGoodsNextPeriodConfigKeyExists) {
			robGoodsConfigDto = robGoodsInfoService.queryRobGoodsConfigDtoByRobGoodsId(robGoodsId);
			if (robGoodsConfigDto != null)
				redis.set(robGoodsNextPeriodConfigKey, robGoodsConfigDto);
		} else
			robGoodsConfigDto = redis.get(robGoodsNextPeriodConfigKey, RobGoodsConfigDto.class);
		
		return robGoodsConfigDto;
	}
	
	private Set<Integer> generateNextPeriodDateSet(String nextPeriodDate) {
		if (StringUtils.isNotBlank(nextPeriodDate)) {
			String[] nextPeriodDateArr = nextPeriodDate.split(",");
			Set<Integer> nextPeriodDateSet = new TreeSet<>();
			for (String tempNextPeriodDate : nextPeriodDateArr)
				nextPeriodDateSet.add(Integer.valueOf(tempNextPeriodDate));
			
			return nextPeriodDateSet;
		}
		return Collections.emptySet();
	}
	
	private Long generateNextPeriodTimeInMills(long currentTimeInMills, Set<Integer> nextPeriodDateSet) {
		int dayOfWeek = DateUtils.getCurrentDayOfWeek(currentTimeInMills);
		Set<Long> nextPeriodDateTimeSet = new TreeSet<>();
		for (Integer nextPeriodDate : nextPeriodDateSet) {
			Long nextPeriodDateTime = null;
			if (dayOfWeek >= nextPeriodDate)
				nextPeriodDateTime = DateUtils.getNextWeekDateTime(nextPeriodDate);
			else if (dayOfWeek < nextPeriodDate)
				nextPeriodDateTime = DateUtils.getCurrentWeekDateTime(nextPeriodDate);
			if (nextPeriodDateTime != null)
				nextPeriodDateTimeSet.add(nextPeriodDateTime);
		}
		
		Long[] nextPeriodTimeArr = {};
		nextPeriodTimeArr = nextPeriodDateTimeSet.toArray(nextPeriodTimeArr);
		return nextPeriodTimeArr[0];
	}

	public List<RobbedGoodsDto> queryRobbedGoodsDtoListByConditon(Long userId,
			int type, int page) {
		int pageIndex = PageUtils.getPageStartIndex(page, PAGE_SIZE);
		List<RobbedGoodsDto> robbedGoodsDtoList = new ArrayList<>();
		List<RobGoodsInfoPeriodDto> robGoodsInfoPeriodDtoList = null;
		switch (type) {
		case 0: {
			robGoodsInfoPeriodDtoList = robGoodsInfoPeriodService.queryUserRobGoodsInfoPeriodDtosByUserId(userId, pageIndex, PAGE_SIZE);
		}
		break;

		case 1 : {
			robGoodsInfoPeriodDtoList = robGoodsInfoPeriodService.queryUserRobGoodsInfoPeriodDtosByUserId(userId, PublishedConstants.NOT_PUBLISHED, pageIndex, PAGE_SIZE);
		}
		break;
			
		case 2 : {
			robGoodsInfoPeriodDtoList = robGoodsInfoPeriodService.queryUserRobGoodsInfoPeriodDtosByUserId(userId, PublishedConstants.PUBLISHED, pageIndex, PAGE_SIZE);
		}
		break;
		
		default:
			break;
		}
		
		if (robGoodsInfoPeriodDtoList == null || robGoodsInfoPeriodDtoList.isEmpty())
			return Collections.emptyList();
		List<Integer> robGoodsIdList = distillRobGoodsId(robGoodsInfoPeriodDtoList);
		Map<Integer, RobGoodsInfoDto> robGoodsInfoDtoMap = robGoodsInfoService.queryRobGoodsInfoDtoMapByRobGoodsIds(robGoodsIdList);
		if (robGoodsInfoDtoMap == null || robGoodsInfoDtoMap.isEmpty())
			return Collections.emptyList();
		
		List<Integer> robGoodsPeriodIdList = distillRobGoodsPeriodIds(robGoodsInfoPeriodDtoList);
		List<RobGoodsPeriodUserPersonTimeDto> robGoodsPeriodUserPersonTimeDtoList = robGoodsPeriodPersonTimeService.queryRobGoodsPeriodUserPersonTimeDtosByUserIdAndRobGoodsPeriodIds(userId, robGoodsPeriodIdList);
		Map<Integer, RobGoodsPeriodUserPersonTimeDto> robUserPtAndNumberMap = generateRobUserPtAndNumberMap(robGoodsPeriodUserPersonTimeDtoList);
		generateRobbedGoodsDtoList(robbedGoodsDtoList, robGoodsInfoDtoMap, robGoodsInfoPeriodDtoList, robUserPtAndNumberMap);
		replaceRobbedGoodsDtoThumbnailUrl(robbedGoodsDtoList, DisplayTypeConstants.WAP.getCode());
		return robbedGoodsDtoList;
	}
	
	private void generateRobbedGoodsDtoList(List<RobbedGoodsDto> robbedGoodsDtoList, Map<Integer, RobGoodsInfoDto> robGoodsInfoDtoMap, List<RobGoodsInfoPeriodDto> robGoodsInfoPeriodDtoList, Map<Integer, RobGoodsPeriodUserPersonTimeDto> robUserPtAndNumberMap) {
		RobbedGoodsDto robbedGoodsDto = null;
		RobGoodsInfoDto robGoodsInfoDto = null;
		RobGoodsInfoPeriodDto robGoodsInfoPeriodDto = null;
		RobGoodsPeriodUserPersonTimeDto robGoodsPeriodUserPersonTimeDto = null;
		int robGoodsInfoPeriodDtoListSize = robGoodsInfoPeriodDtoList.size();
		for (int i = 0; i < robGoodsInfoPeriodDtoListSize; i++) {
			robbedGoodsDto = new RobbedGoodsDto();
			robGoodsInfoPeriodDto = robGoodsInfoPeriodDtoList.get(i);
			robbedGoodsDto.setDisplayPeriod(robGoodsInfoPeriodDto.getDisplayPeriod());
			int robGoodsId = robGoodsInfoPeriodDto.getRobGoodsId();
			robbedGoodsDto.setRobGoodsId(robGoodsId);
			robbedGoodsDto.setPublished(robGoodsInfoPeriodDto.getPublished());
			robbedGoodsDto.setEnded(robGoodsInfoPeriodDto.getEnded());
			if (robGoodsInfoDtoMap.containsKey(robGoodsId)) {
				robGoodsInfoDto = robGoodsInfoDtoMap.get(robGoodsId);
				robbedGoodsDto.setGoodsId(robGoodsInfoDto.getGoodsId());
				robbedGoodsDto.setTitle(robGoodsInfoDto.getTitle());
				robbedGoodsDto.setThumbnailWapUrl(robGoodsInfoDto.getThumbnailWapUrl());
				robbedGoodsDto.setThumbnailWebUrl(robGoodsInfoDto.getThumbnailWebUrl());
			}
			if (StringUtils.isNotBlank(robGoodsInfoPeriodDto.getRobUserNickname()))
				robbedGoodsDto.setOwnerNickname(robGoodsInfoPeriodDto.getRobUserNickname());
			if (robGoodsInfoPeriodDto.getRobUserPt() != null)
				robbedGoodsDto.setOwnerPt(robGoodsInfoPeriodDto.getRobUserPt());
			int robGoodsPeriodId = robGoodsInfoPeriodDto.getId();
			if (robUserPtAndNumberMap.containsKey(robGoodsPeriodId)) {
				robGoodsPeriodUserPersonTimeDto = robUserPtAndNumberMap.get(robGoodsPeriodId);
				robbedGoodsDto.setRobUserPt(robGoodsPeriodUserPersonTimeDto.getRobUserPt());
				robbedGoodsDto.setRobUserNumber(robGoodsPeriodUserPersonTimeDto.getRobUserNumber());
			}
			robbedGoodsDtoList.add(robbedGoodsDto);
		}
	}
	
	private List<Integer> distillRobGoodsPeriodIds(List<RobGoodsInfoPeriodDto> robGoodsInfoPeriodDtoList) {
		List<Integer> robGoodsPeriodIdList = new ArrayList<>();
		RobGoodsInfoPeriodDto robGoodsInfoPeriodDto = null;
		int robGoodsInfoPeriodDtoListSize = robGoodsInfoPeriodDtoList.size();
		for (int i = 0; i < robGoodsInfoPeriodDtoListSize; i++) {
			robGoodsInfoPeriodDto = robGoodsInfoPeriodDtoList.get(i);
			robGoodsPeriodIdList.add(robGoodsInfoPeriodDto.getId());
		}
		return robGoodsPeriodIdList;
	}

	private List<Integer> distillRobGoodsId(List<RobGoodsInfoPeriodDto> robGoodsInfoPeriodDtoList) {
		List<Integer> robGoodsIdList = new ArrayList<>();
		RobGoodsInfoPeriodDto robGoodsInfoPeriodDto = null;
		int robGoodsInfoPeriodDtoListSize = robGoodsInfoPeriodDtoList.size();
		for (int i = 0; i < robGoodsInfoPeriodDtoListSize; i++) {
			robGoodsInfoPeriodDto = robGoodsInfoPeriodDtoList.get(i);
			if (!robGoodsIdList.contains(robGoodsInfoPeriodDto.getRobGoodsId()))
				robGoodsIdList.add(robGoodsInfoPeriodDto.getRobGoodsId());
		}
		return robGoodsIdList;
	}
}
